package com.cenxi.common.util;

import cn.hutool.core.convert.Convert;
import com.cenxi.common.constants.SecurityConstants;
import com.cenxi.common.constants.TokenConstants;
import com.cenxi.common.dto.LoginUserDTO;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.HashMap;
import java.util.Map;

/**
 * Jwt工具类
 *
 * @author baron
 */
public class JwtUtils {
    public static final  String SECRET = TokenConstants.SECRET;

    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    public static String createToken(Map<String, Object> claims) {
        return Jwts.builder().
                setClaims(claims).
                signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }

    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    public static Claims parseToken(String token) {
        return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
    }

    /**
     * 根据令牌获取用户标识
     *
     * @param token 令牌
     * @return 用户ID
     */
    public static String getUserKey(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstants.USER_KEY);
    }

    /**
     * 根据令牌获取用户标识
     *
     * @param claims 身份信息
     * @return 用户ID
     */
    public static String getUserKey(Claims claims) {
        return getValue(claims, SecurityConstants.USER_KEY);
    }

    /**
     * 根据令牌获取用户ID
     *
     * @param token 令牌
     * @return 用户ID
     */
    public static String getUserId(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstants.DETAILS_USER_ID);
    }

    /**
     * 根据身份信息获取用户ID
     *
     * @param claims 身份信息
     * @return 用户ID
     */
    public static String getUserId(Claims claims) {
        return getValue(claims, SecurityConstants.DETAILS_USER_ID);
    }

    /**
     * 根据令牌获取用户名
     *
     * @param token 令牌
     * @return 用户名
     */
    public static String getUserName(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstants.DETAILS_USERNAME);
    }

    /**
     * 根据身份信息获取用户名
     *
     * @param claims 身份信息
     * @return 用户名
     */
    public static String getUserName(Claims claims) {
        return getValue(claims, SecurityConstants.DETAILS_USERNAME);
    }


    public static String getSystem(String token) {
        Claims claims = parseToken(token);
        return getValue(claims, SecurityConstants.DETAILS_SYSTEM);
    }

    /**
     * 根据身份信息获取用户所属系统
     *
     * @param claims
     * @return 所属系统
     */
    public static String getSystem(Claims claims) {
        return getValue(claims, SecurityConstants.DETAILS_SYSTEM);
    }

    /**
     * 根据身份信息获取键值
     *
     * @param claims 身份信息
     * @param key    键
     * @return 值
     */
    public static String getValue(Claims claims, String key) {
        return Convert.toStr(claims.get(key), "");
    }

    /**
     * 创建令牌
     */
    public static Map<String, Object> createTokenDTO(LoginUserDTO loginUser) {
        long expiresTime = SecurityConstants.TIME;
        Long userId = Long.valueOf(loginUser.getUserId());
        String userName = loginUser.getUserName();
        // Jwt存储信息
        Map<String, Object> claimsMap = new HashMap<String, Object>();
        claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);
        claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
        claimsMap.put(SecurityConstants.EXPIRES_TIME, expiresTime);

        // 接口返回信息
        Map<String, Object> rspMap = new HashMap<String, Object>();
        rspMap.put("access_token", JwtUtils.createToken(claimsMap));
        rspMap.put("expires_in", expiresTime);
        return rspMap;
    }

    public static void main(String[] args) {
        //demo
        LoginUserDTO loginUserDTO = new LoginUserDTO();
        loginUserDTO.setUserId("1");
        loginUserDTO.setUserName("小张");
        Map<String, Object> tokenDTO = JwtUtils.createTokenDTO(loginUserDTO);
        Object access_token = tokenDTO.get("access_token");
        System.out.println(access_token);
    }
}
